package com.gxa.eshops.sso.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gxa.eshops.sso.entity.User;
import com.gxa.eshops.sso.repository.UserRepository;
import com.gxa.eshops.sso.service.UserService;
import com.gxa.eshops.sso.util.GetIpUtil;
import com.gxa.eshps.cores.exception.BusinessException;
import com.gxa.eshps.cores.exception.ExceptionCode;
import com.gxa.eshps.cores.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @program: IntelliJ IDEA
 * @description:
 * @author: Mr.Wang
 * @create: 2022-07-06 11:22
 **/
@Service
@Transactional(rollbackFor = Throwable.class)
public class UserServiceImpl implements UserService {
    @Autowired
    RedisTemplate<String ,Object> redisTemplate;
    @Autowired
    UserRepository userRepository;
    @Autowired
    HttpServletRequest httpServletRequest;

    private static final String SALT = "wangpeng";

    @Override
    public String login(String phone, String code) throws Exception{
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        //获取redis存的验证码
        Object redisCode =opsForValue.get(SmsServiceImpl.LOGIN_SMS + phone);
        //验证码过期
        if (StringUtils.isEmpty(redisCode)){
            throw new BusinessException(ExceptionCode.EXPIRE_CODE);
        }
        //验证码错误
        if (!code.equals(redisCode)){
            throw new BusinessException(ExceptionCode.WRONG_CODE);
        } else {
            //验证码通过校验则删除
            redisTemplate.delete(SmsServiceImpl.LOGIN_SMS + phone);
        }
        //如果用户不存在,则创建
        User findUser = userRepository.findUserByPhone(phone);
        if (findUser!=null){
        //删除Redis上次登录保存的token
        redisTemplate.delete(findUser.getToken());
            //账户状态异常
            if (!findUser.getStatus().equals(1)){
                throw new BusinessException(ExceptionCode.WRONG_USER_STATUS);
            }
        } else {
            findUser=new User();
            findUser.setName("user"+phone);
            findUser.setPhone(phone);
            findUser.setStatus(1);
        }
        //设置登录时间和登录IP
        findUser.setLastLoginTime(LocalDateTime.now());
        //调用获取IP的工具类
        findUser.setIpAddress(GetIpUtil.getIpAddress(httpServletRequest));
        //前端传递登录类型
        findUser.setLoginType(2);
        String token = UUID.randomUUID().toString().replace("-", "");
        //设置token,覆盖数据库上次登录保存的token
        findUser.setToken(token);
        //pc:2小时,手机端H5:2小时,app:1个月
        final int pcNum = 1;
        final int phoneNum = 2;
        final int expire;
        if (findUser.getLoginType()==pcNum){
            expire = 2;
        }else if (findUser.getLoginType()==phoneNum){
            expire = 2;
        } else {
            expire = 24*31;
        }
        //不管是登录还是注册,save方法都要执行,保存到数据库(更新token)并返回最新的user对象
        User save = userRepository.save(findUser);
        //redis添加token和登录过期时间
        ObjectMapper objectMapper = new ObjectMapper();
        //调用了toString方法
        String value = objectMapper.writeValueAsString(save);
        //把带id值的user对象缓存到Redis
        String key = SALT+token;
        redisTemplate.opsForValue().set(key, value, expire, TimeUnit.HOURS);
        return token;
    }

    @Override
    public User checkWithToken(String token) throws Exception {
        String key = SALT + token;
        Object redisToken = redisTemplate.opsForValue().get(key);
        //token错误或不存在则返回结果为空
        if (redisToken == null) {
            throw new BusinessException(ExceptionCode.WRONG_TOKEN);
        }
        //将token保存的用户转换回user对象
        ObjectMapper objectMapper = new ObjectMapper();
        User user = objectMapper.readValue(redisToken.toString(), User.class);
        //延长登录时间,更新登录时间
        user.setLastLoginTime(LocalDateTime.now());
        String value = objectMapper.writeValueAsString(user);
        redisTemplate.opsForValue().set(key,value,2,TimeUnit.HOURS);
        return user;
    }
}
